/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package yassp.client;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import yassp.Code;

/**
 *
 * @author Milridor
 */
public class Command {

    private int commandCode;
    private String operand;
    private Folder folder;

    public Command(int commandCode, String operand) {
        this.commandCode = commandCode;
        this.operand = operand;
    }

    //Cette méthode renvoie un PipedInputStream que Connection doit lire et envoyer
    PipedInputStream getCommand() throws IOException {
        PipedOutputStream out = new PipedOutputStream();
        PipedInputStream in = new PipedInputStream(out);
        DataOutputStream dout = new DataOutputStream(out);
        dout.writeInt(commandCode);
        dout.flush();
        switch (commandCode) {
            case Code.PUSHFILE:
                dout.close();
                FileReaderThread FRT = new FileReaderThread(operand, out);
                FRT.start();
                break;

            case Code.PULLFILE:
                if(FileStore.hashExist(operand))
                    return null;
            case Code.PULLROOT:
            case Code.PULLFOLDER:
                dout.writeUTF(operand);
                dout.close();
                out.close();
                break;
            case Code.PUSHROOT:
                operand = ClientApp.root.serialize("/");
            case Code.PUSHFOLDER:
                //TODO: Faire ça dans un thread séparé pour les gros dossiers
                dout.writeUTF(operand);
                dout.close();
                out.close();
                break;
        }
        return in;
    }

    void recvResponse(BufferedInputStream stream) {
        try {
            DataInputStream dis = new DataInputStream(stream);
            int code = dis.readInt();
            if (code == Code.OK) {
                switch (commandCode) {
                    case Code.PUSHFILE:
                    case Code.PUSHROOT:
                    case Code.PUSHFOLDER:
                        //On a plus rien à faire
                        break;

                    case Code.PULLROOT:
                    case Code.PULLFOLDER:
                        Folder root = ClientApp.root;
                        try {
                            root.deserialize(dis, "/", operand);
                        } catch (NoSuchAlgorithmException ex) {
                            Logger.getLogger(Command.class.getName()).log(Level.SEVERE, null, ex);
                        }
                        break;

                    case Code.PULLFILE:
                        PipedOutputStream pos = new PipedOutputStream();
                        PipedInputStream pis = new PipedInputStream(pos);

                        FileWriterThread FWT = new FileWriterThread(operand,pis);
                        FWT.start();
                        
                        Long size = dis.readLong();
                        byte[] buffer = new byte[256];
                        while(size > 0) {
                            int c = dis.read(buffer, 0, (int)Math.min(size,256));
                            if(c == -1)
                                break;
                            size -= c;
                            pos.write(buffer, 0, c);
                        }
                        pos.close();
                }
            } else {
                //TODO: logguer cette erreur
            }
        } catch (IOException ex) {
            Logger.getLogger(Command.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
